page.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import Link from "next/link";
  2. import { notFound } from "next/navigation";
  3. import { AgentAvatar } from "@/components/agents/agent-avatar";
  4. import { loadAgentFeed } from "@/lib/agent-monitor";
  5. const statusClassMap = {
  6. working: "status-pill status-pill--working",
  7. idle: "status-pill status-pill--idle",
  8. warning: "status-pill status-pill--warning",
  9. offline: "status-pill status-pill--offline"
  10. } as const;
  11. type AgentDetailPageProps = {
  12. params: Promise<{
  13. agentId: string;
  14. }>;
  15. };
  16. export default async function AgentDetailPage({ params }: AgentDetailPageProps) {
  17. const { agentId } = await params;
  18. const feed = await loadAgentFeed("all");
  19. const agent = feed.agents.find((item) => item.id === agentId);
  20. if (!agent) {
  21. notFound();
  22. }
  23. return (
  24. <main className="page-shell">
  25. <section className="page-title">
  26. <h1>{agent.name}</h1>
  27. <p>这里保留单个 agent 的详细监控页,重点看当前任务、最近输出、心跳、队列和异常。</p>
  28. </section>
  29. <section className="agents-shell">
  30. <div className="agent-detail-hero">
  31. <div className="agent-detail-hero__main">
  32. <div className="agent-card__header">
  33. <AgentAvatar kind={agent.avatarKind} label={agent.name} large />
  34. <div>
  35. <div className="agent-card__name">{agent.name}</div>
  36. <div className="agent-card__role">{agent.role}</div>
  37. <div className="chip-row" style={{ marginTop: 14 }}>
  38. <span className={statusClassMap[agent.status]}>{agent.statusLabel}</span>
  39. <span className="chip">主机 {agent.host}</span>
  40. <span className="chip">Owner {agent.owner}</span>
  41. </div>
  42. </div>
  43. </div>
  44. </div>
  45. <div className="agent-detail-hero__actions">
  46. <Link className="button button--secondary" href="/agents">
  47. 返回总览
  48. </Link>
  49. </div>
  50. </div>
  51. <div className="agent-detail-grid">
  52. <div className="reader-panel" style={{ padding: 20 }}>
  53. <div className="agent-detail-section__title">运行状态</div>
  54. <div className="agent-detail-list">
  55. <div className="agent-row">
  56. <div className="agent-row__label">当前状态</div>
  57. <div className="agent-row__value agent-row__value--strong">{agent.statusLabel}</div>
  58. </div>
  59. <div className="agent-row">
  60. <div className="agent-row__label">最近心跳</div>
  61. <div className="agent-row__value">{agent.lastHeartbeat}</div>
  62. </div>
  63. <div className="agent-row">
  64. <div className="agent-row__label">运行时长</div>
  65. <div className="agent-row__value">{agent.uptime}</div>
  66. </div>
  67. <div className="agent-row">
  68. <div className="agent-row__label">最近刷新</div>
  69. <div className="agent-row__value">{agent.updatedAt}</div>
  70. </div>
  71. </div>
  72. </div>
  73. <div className="reader-panel" style={{ padding: 20 }}>
  74. <div className="agent-detail-section__title">任务指标</div>
  75. <div className="agent-quick-grid">
  76. <div className="agent-mini-stat">
  77. <span>任务ID</span>
  78. <strong>{agent.taskId}</strong>
  79. </div>
  80. <div className="agent-mini-stat">
  81. <span>阶段</span>
  82. <strong>{agent.taskStage}</strong>
  83. </div>
  84. <div className="agent-mini-stat">
  85. <span>队列深度</span>
  86. <strong>{agent.queueDepth}</strong>
  87. </div>
  88. <div className="agent-mini-stat">
  89. <span>今日完成</span>
  90. <strong>{agent.todayCompleted}</strong>
  91. </div>
  92. </div>
  93. </div>
  94. <div className="reader-panel" style={{ padding: 20 }}>
  95. <div className="agent-detail-section__title">当前任务</div>
  96. <div className="agent-detail-highlight">{agent.currentTask}</div>
  97. </div>
  98. <div className="reader-panel" style={{ padding: 20 }}>
  99. <div className="agent-detail-section__title">最近输出</div>
  100. <div className="agent-detail-paragraph">{agent.lastOutput}</div>
  101. {agent.lastError ? <div className="agent-detail-note">异常标记: {agent.lastError}</div> : null}
  102. </div>
  103. </div>
  104. </section>
  105. </main>
  106. );
  107. }